/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Mcu_PvtSens.c                                                                              *
 * \brief    AUTOSAR 4.3.1 MCAL Mcu Driver                                                              *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2023/08/02     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "RegHelper.h"
#include "__regs_base.h"
#include "SchM_McuExt.h"
#include "McuExt_PvtSens.h"
#include "McuExt_Types.h"
#include "McuExt_Cfg.h"
#include "McuExt_Fault.h"
/********************************************************************************************************
 *                                 Private Macro definition                                             *
 *******************************************************************************************************/
/** \brief  Get module config pointer. */
#define MCUEXT_PVT_GET_CONFIGPTR()                            (McuExt_PvtConfigPtr)

/** \brief  Get module device infopointer. */
#define MCUEXT_PVT_GET_DEVICEINFO()                           (&McuExt_PvtSfDev)

/* Length of PVT DOUT and Threshold register bits. */
#define PVT_THRESH_BITS (12U)

/* PVT registers */
#define PVT_CHANNEL_REG_OFFSET (0x34U)
#define PVT_CHANNEL_REGISTER(channel, reg) (((uint32)(channel)*PVT_CHANNEL_REG_OFFSET) + (reg))

#define PVT_CTRL (0x0U)
#define PVT_CTRL_HL_MODE_EN(channel) (8U + ((uint32)(channel)*2U))
#define PVT_CTRL_RF_MODE_EN(channel) (9U + ((uint32)(channel)*2U))

#define PVT_DOUT (0x4U)
#define PVT_DOUT_VALID 0U
#define PVT_DOUT_DOUT 1U
#define PVT_HYST_H(channel) PVT_CHANNEL_REGISTER(channel, 0x8U)

#define PVT_HYST_H_THRESH_H 0U
#define PVT_HYST_H_THRESH_L 12U

#define PVT_HYST_L(channel) PVT_CHANNEL_REGISTER(channel, 0xcU)
#define PVT_HYST_L_THRESH_H 0U
#define PVT_HYST_L_THRESH_L 12U

#define PVT_HYST_R(channel) PVT_CHANNEL_REGISTER(channel, 0x10U)
#define PVT_HYST_R_ALARM 0U
#define PVT_HYST_R_HYST 12U

#define PVT_HYST_F(channel) PVT_CHANNEL_REGISTER(channel, 0x14U)
#define PVT_HYST_F_ALARM 0U
#define PVT_HYST_F_HYST 12U

#define PVT_INT_EN(channel) PVT_CHANNEL_REGISTER(channel, 0x30U)
#define PVT_INT_STATUS(channel) PVT_CHANNEL_REGISTER(channel, 0x34U)
#define PVT_INT_CLR(channel) PVT_CHANNEL_REGISTER(channel, 0x38U)

#define PVT_ALARM_INT(alarm) (uint32)(alarm)

#define PVT_EXTRA_CFG (0x70U)
#define PVT_EXTRA_CFG_PVT_PMU_INT_1_EN (13U)
#define PVT_EXTRA_CFG_PVT_PMU_INT_0_EN (12U)

#define PVT_BIT_MASK(x) ((1UL << (x)) - 1UL)
#define PVT_BIT_SET(x, bit) ((0U != ((x) & ((uint32)1UL << (bit)))) ? 1U : 0U)
/********************************************************************************************************
 *                                  Private Variable Definitions                                        *
 *******************************************************************************************************/
#define MCUEXT_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "McuExt_MemMap.h"
MCUEXT_LOCAL const McuExt_PvtAlarmConfigType *McuExt_PvtConfigPtr;
#define MCUEXT_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "McuExt_MemMap.h"
/********************************************************************************************************
 *                                  Global Constant Declarations                                        *
 *******************************************************************************************************/
#define MCUEXT_START_SEC_VAR_INIT_UNSPECIFIED
#include "McuExt_MemMap.h"
/*PRQA S 0704 4*/
MCUEXT_LOCAL McuExt_PvtType McuExt_PvtSfDev =
{
    APB_PT_SNS_SF_BASE,
    {
        {NULL_PTR, 0},
        {NULL_PTR, 0},
    }
};
#define MCUEXT_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "McuExt_MemMap.h"
/********************************************************************************************************
 *                                  Private Function Declarations                                       *
 *******************************************************************************************************/
#define MCUEXT_START_SEC_CODE
#include "McuExt_MemMap.h"
/** *****************************************************************************************************
 * \brief Convert DOUT register value to Celsius.
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL inline float32 McuExt_Ip_PvtDoutToCelsius(uint32 dout)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : dout - pvt register dout
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Celsius
 *
 * Description        : Convert DOUT register value to Celsius.
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL inline float32 McuExt_Ip_PvtDoutToCelsius(uint32 dout)
{
    uint32 value = dout;

    return (306.76f * (float32)value / (float32)4096U) - 75.98f;
}

/** *****************************************************************************************************
 * \brief Convert Celsius to DOUT register value.
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL inline uint32 McuExt_Ip_PvtCelsiusToDout(float32 celsius)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : celsius
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : DOUT register value
 *
 * Description        : Convert Celsius to DOUT register value.
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL inline uint32 McuExt_Ip_PvtCelsiusToDout(float32 celsius)
{
    /* PRQA S 4395,4119 1*/
    uint32 dout = (uint32)(((celsius + 75.98f) * 4096.0f) / 306.76f);
    return dout & PVT_BIT_MASK(PVT_THRESH_BITS);
}

/** *****************************************************************************************************
 * \brief is pvt running.
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL boolean McuExt_Ip_PvtIsTempSensorRunning(McuExt_PvtType *devPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : is pvt running, TRUE:running; FALSE: not running
 *
 * Description        : is pvt running.
 * \endverbatim
 *******************************************************************************************************/
/* PRQA S 3673 1 */
MCUEXT_LOCAL boolean McuExt_Ip_PvtIsTempSensorRunning(McuExt_PvtType *devPtr)
{
    boolean ret;
    /*PRQA S 2985 1*/
    uint32 ctrl = readl(devPtr->base + PVT_CTRL);

    if (((ctrl & BM_PVT_CTRL_PDTSEN) == 0U) ||
        ((ctrl & BM_PVT_CTRL_PTSEL) == 0U))
    {
        ret = TRUE;
    }
    else
    {
        ret = FALSE;
    }

    McuExtHookBegin_McuExt_Ip_PvtIsTempSensorRunning();

    return ret;
}

#define MCUEXT_STOP_SEC_CODE
#include "McuExt_MemMap.h"

#define MCUEXT_START_SEC_CODE_FAST
#include "McuExt_MemMap.h"
/** *****************************************************************************************************
 * \brief Pvt irq handler.
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtIrqHandler(uint8 controllerId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : controllerId - 0/1/2/3 for sf channel0/1, ap channel 0/1
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Pvt irq handler.
 * \endverbatim
 * Traceability       : SW_SM003 SW_SM004
 *******************************************************************************************************/
void McuExt_Ip_PvtIrqHandler(uint8 channel)
{
    McuExt_PvtType *devPtr = &McuExt_PvtSfDev;
    uint32 base;
    uint32 en;
    uint32 status;
#if (MCUEXT_PVT_ENABLE_NOTIFICATION_API == STD_ON)
    const McuExt_PvtChannelType *channelPtr;
    uint32 ent;
    uint32 statust;
    uint32 index;
#endif /** #if (MCUEXT_PVT_ENABLE_NOTIFICATION_API == STD_ON) */
    Std_ReturnType ret;
    boolean isRun;

    McuExtHookBegin_McuExt_Ip_PvtIrqHandlerChannel();

    if (channel < (uint8)PVT_CHANNEL_NUMBER)
    {
        base = devPtr->base;

        en = readl(base + PVT_INT_EN(channel));
        status = readl(base + PVT_INT_STATUS(channel));

        isRun = McuExt_Ip_PvtIsTempSensorRunning(devPtr);

        McuExtHookBegin_McuExt_Ip_PvtIrqHandler();

        ret = ((McuExt_PvtInitializeState == MCUEXT_PVT_INIT) ? E_OK : E_NOT_OK);

        if ((E_OK != ret) || (FALSE == isRun) || (0U == (en & status)))
        {
            McuExtHookEnd_McuExt_Ip_PvtIrqHandler();
            /* Write 1 Clear interrupt status */
            writel(status, base + PVT_INT_CLR(channel));
            /* Write 0 after Clear interrupt status */
            writel(0x00U, base + PVT_INT_CLR(channel));
            /* Deinit the device. */
            McuExt_Ip_PvtDeinit();
        }
        else
        {
#if (MCUEXT_PVT_ENABLE_NOTIFICATION_API == STD_ON)

            channelPtr = &(devPtr->channel[channel]);

            for (index = (uint32)PVT_HIGH_LEVEL_ALARM; index < (uint32)PVT_ALARM_NR; index++)
            {
                ent = PVT_BIT_SET(en, index);
                statust = PVT_BIT_SET(status, index);

                if ((TRUE == ent) && (TRUE == statust))
                {
                    if (channelPtr->alarmCb != NULL_PTR)
                    {
                        /* Call user alarm callback. */
                        /* PRQA S 4342 1*/
                        channelPtr->alarmCb((McuExt_PvtChannelIdType)channel, (McuExt_PvtAlarmType)index);
                    }
                }

                /*
                * Try to clear interrupt status. Level interrupt status are
                * cleared when INT_CLR bits are set, and DOUT has returned to
                * normal range. Edge interrupt status are cleared when INT_CLR
                * bits are set.
                *
                * Note that INT_CLR itself is not auto cleared, so we have to
                * clear INT_CLR manually.
                */
            }
#endif /** #if (MCUEXT_PVT_ENABLE_NOTIFICATION_API == STD_ON) */

            writel(status, base + PVT_INT_CLR(channel));
            writel(0x00U, base + PVT_INT_CLR(channel));
        }
    }

    McuExtHookEnd_McuExt_Ip_PvtIrqHandler();

    return;
}
#define MCUEXT_STOP_SEC_CODE_FAST
#include "McuExt_MemMap.h"

#define MCUEXT_START_SEC_CODE
#include "McuExt_MemMap.h"
/** *****************************************************************************************************
 * \brief Enable/disable alarm interrupt en
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtUpdateAlarmIrq(const McuExt_PvtType *devPtr, McuExt_PvtChannelIdType channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : Enable/disable alarm interrupt en
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL void McuExt_Ip_PvtUpdateAlarmIrq(const McuExt_PvtType *devPtr,
        McuExt_PvtChannelIdType channel)
{
    /* PRQA S 3678 1 */
    const McuExt_PvtChannelType *channelPtr = (const McuExt_PvtChannelType *)&devPtr->channel[channel];
    uint32 base;
    McuExt_PvtAlarmType alarm;
    uint32 regValue;
#if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON)
    uint32 safetyInterruptMask;
#endif /** #if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON) */

    base = devPtr->base;

    regValue = readl(base + PVT_CTRL);

    /* Update High/Low mode bit in PVT_CTRL register, which controls
    * Temperature and Process High/Low modes.
    */
    if (((channelPtr->alarmEnableMask & (1UL << (uint32)PVT_HIGH_LEVEL_ALARM)) != 0U) ||
        ((channelPtr->alarmEnableMask & (1UL << (uint32)PVT_LOW_LEVEL_ALARM)) != 0U))
    {
        regValue |= (1UL << PVT_CTRL_HL_MODE_EN(channel));
    }
    else
    {
        /* Caution: Before ANA_PTSENSOR is enabled, hyst status function settingof all used
            channels should be configured as needed.
            Otherwise, this may cause unexpected PVT_INT or PVT_PMU_INT asserts
        */
        regValue &= ~(1UL << PVT_CTRL_HL_MODE_EN(channel));
    }

    if (((channelPtr->alarmEnableMask & (1UL << (uint32)PVT_RISING_EDGE_ALARM)) != 0U) ||
        ((channelPtr->alarmEnableMask & (1UL << (uint32)PVT_FALLING_EDGE_ALARM)) != 0U))
    {
        regValue |= (1UL << PVT_CTRL_RF_MODE_EN(channel));
    }
    else
    {
        /* Caution: Before ANA_PTSENSOR is enabled, hyst status function settingof all used
            channels should be configured as needed.
            Otherwise, this may cause unexpected PVT_INT or PVT_PMU_INT asserts
        */
        regValue &= ~(1UL << PVT_CTRL_RF_MODE_EN(channel));
    }

    writel(regValue, base + PVT_CTRL);

    /* Enable alarm interrupt if necessary. */
    if (channelPtr->alarmEnableMask != 0U)
    {
        regValue = readl(base + PVT_INT_EN(channel));
#if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON)
        safetyInterruptMask = readl(base + PVT_SEM_IRQ_CTRL_OFF);
#endif /** #if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON) */

        /* PRQA S 4527 1*/
        for (alarm = PVT_HIGH_LEVEL_ALARM; alarm < PVT_ALARM_NR; alarm++)
        {
            if ((channelPtr->alarmEnableMask & (1UL << (uint32)alarm)) != 0U)
            {
                regValue |= (1UL << PVT_ALARM_INT(alarm));
            }
            else
            {
                regValue &= ~(1UL << PVT_ALARM_INT(alarm));
            }
        }

        writel(regValue, base + PVT_INT_EN(channel));
#if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON)

        if (PVT_CHANNEL0 == channel)
        {
            safetyInterruptMask |= channelPtr->alarmEnableMask;
        }
        else
        {
            safetyInterruptMask |= (channelPtr->alarmEnableMask << 8U);
        }

        writel(safetyInterruptMask, base + PVT_SEM_IRQ_CTRL_OFF);
#endif /** #if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON) */
    }
}

/** *****************************************************************************************************
 * \brief Enable/disable alarm mask bit and interrupt en
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtUpdateAlarmMode(McuExt_PvtType *devPtr,
 *                                                      McuExt_PvtChannelIdType channel,
                                                        McuExt_PvtAlarmType alarm, boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel
 *                      alarm - alarm type
 *                      enable - TRUE:ON,FALSE:OFF
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : Enable/disable alarm mask bit and interrupt en
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL void McuExt_Ip_PvtUpdateAlarmMode(McuExt_PvtType *devPtr,
        McuExt_PvtChannelIdType channel,
        McuExt_PvtAlarmType alarm, boolean enable)
{
    McuExt_PvtChannelType *channelPtr = (McuExt_PvtChannelType *)&devPtr->channel[channel];

    SchM_Enter_McuExt_MCUEXT_EXCLUSIVE_AREA_00();

    if (TRUE == enable)
    {
        channelPtr->alarmEnableMask |= ((uint32)1U << (uint32)alarm);
    }
    else
    {
        channelPtr->alarmEnableMask &= ~((uint32)1U << (uint32)alarm);
    }

    SchM_Exit_McuExt_MCUEXT_EXCLUSIVE_AREA_00();

    McuExt_Ip_PvtUpdateAlarmIrq(devPtr, channel);

}
/** *****************************************************************************************************
 * \brief pvt variable initialization
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtPrepare(McuExt_PvtType *devPtr,
 *                                                                  McuExt_PvtAlarmConfigType *configPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : pvt variable initialization
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL void McuExt_Ip_PvtPrepare(McuExt_PvtType *devPtr,
                                       const McuExt_PvtAlarmConfigType *configPtr)
{
    uint32 base;
    uint32 channel;
    McuExt_PvtChannelType *channelPtr;

    base = devPtr->base;

    for (channel = (uint32)PVT_CHANNEL0; channel < (uint32)PVT_CHANNEL_NUMBER; channel++)
    {
        /* PRQA S 4342 1*/
        channelPtr = (McuExt_PvtChannelType *)&devPtr->channel[channel];

        /* Disable all interrupts by default. */
        writel(0U, base + PVT_INT_EN(channel));

        channelPtr->alarmCb = NULL_PTR;
        channelPtr->alarmEnableMask = 0U;
    }

    McuExt_PvtConfigPtr = configPtr;
}

/** *****************************************************************************************************
 * \brief start pvt sensor
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtStart(McuExt_PvtType *devPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : start pvt sensor
 * \endverbatim
 *******************************************************************************************************/
/* PRQA S 3673 2 */
MCUEXT_LOCAL void McuExt_Ip_PvtStart(McuExt_PvtType *devPtr)
{
    uint32 regValue = readl(devPtr->base + PVT_CTRL);

    /* Disable T sensor */
    regValue |= BM_PVT_CTRL_PDTSEN;
    writel(regValue, devPtr->base + PVT_CTRL);

    /* Select temperature sensor output. */
    regValue &= ~BM_PVT_CTRL_PTSEL;
    writel(regValue, devPtr->base + PVT_CTRL);

    /* Enable T sensor. */
    regValue &= ~BM_PVT_CTRL_PDTSEN;
    writel(regValue, devPtr->base + PVT_CTRL);

}

/** *****************************************************************************************************
 * \brief register callback
 *
 * \verbatim
 * Syntax             : MCUEXT_LOCAL void McuExt_Ip_PvtRegisterAlarmCb(McuExt_PvtType *devPtr, McuExt_PvtChannelIdType channel,
        Mcu_PvtAlarmCbType alarmCb)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel
 *                      alarmCb - callback
 *                      argPtr - callback arg
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : register callback
 * \endverbatim
 *******************************************************************************************************/
MCUEXT_LOCAL void McuExt_Ip_PvtRegisterAlarmCb(McuExt_PvtType *devPtr,
        McuExt_PvtChannelIdType channel,
        Mcu_PvtAlarmCbType alarmCb)
{
    McuExt_PvtChannelType *channelPtr= (McuExt_PvtChannelType *)&devPtr->channel[channel];

    channelPtr->alarmCb = alarmCb;
    McuExt_Ip_PvtUpdateAlarmIrq(devPtr, channel);
}

/********************************************************************************************************
 *                                  Global Function Declarations                                        *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief This function enable the alarm according to channel and alarm type for pvt.
 *
 * \verbatim
 * Syntax             : Std_ReturnType McuExt_Ip_PvtEnableAlarm(McuExt_PvtType *devPtr, McuExt_PvtChannelIdType channel,
                                     McuExt_PvtAlarmType alarm)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel id
 *                      alarm - alarm type
 *                      configPtr - pointer to pvt config data
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function enable the alarm according to channel and alarm type for pvt.
 * \endverbatim
 *******************************************************************************************************/
/*PRQA S 1505 1*/
MCUEXT_LOCAL Std_ReturnType McuExt_Ip_PvtEnableAlarm(McuExt_PvtType *devPtr,
        McuExt_PvtChannelIdType channel,
        McuExt_PvtAlarmType alarm)
{
    Std_ReturnType errorId = E_OK;
    uint32 regValue;
    const McuExt_PvtAlarmConfigType *alarmConfigPtr;

    McuExtHookBegin_McuExt_Ip_PvtEnableAlarm();

    if (channel >= PVT_CHANNEL_NUMBER)
    {
        errorId = MCUEXT_E_INVALID_PARAM;
    }
    else
    {
        if (FALSE == McuExt_Ip_PvtIsTempSensorRunning(devPtr))
        {
            errorId = MCUEXT_E_PVT_STOP;
        }
        else
        {
            alarmConfigPtr = MCUEXT_PVT_GET_CONFIGPTR();

            switch (alarm)
            {
            case PVT_HIGH_LEVEL_ALARM:
                regValue = FV_PVT_C0_HYST_H_SET_THRESH_H(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].levelAlarm.threshHigh));
                regValue |= FV_PVT_C0_HYST_H_SET_THRESH_L(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].levelAlarm.threshHigh - 0.1f));
                writel(regValue, devPtr->base + PVT_HYST_H(channel));
                break;

            case PVT_LOW_LEVEL_ALARM:
                regValue = FV_PVT_C0_HYST_L_SET_THRESH_H(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].levelAlarm.threshLow));
                regValue |= FV_PVT_C0_HYST_L_SET_THRESH_L(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].levelAlarm.threshLow - 0.1f));
                writel(regValue, devPtr->base + PVT_HYST_L(channel));
                break;

            case PVT_RISING_EDGE_ALARM:
                regValue = FV_PVT_C0_HYST_R_SET_THRESH_HYST(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].risingEdgeAlarm.hyst));
                regValue |= FV_PVT_C0_HYST_R_SET_THRESH_ALARM(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].risingEdgeAlarm.alarm));
                writel(regValue, devPtr->base + PVT_HYST_R(channel));
                break;

            case PVT_FALLING_EDGE_ALARM:
                regValue = FV_PVT_C0_HYST_F_SET_THRESH_HYST(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].fallingEdgeAlarm.hyst));
                regValue |= FV_PVT_C0_HYST_F_SET_THRESH_ALARM(McuExt_Ip_PvtCelsiusToDout(
                                alarmConfigPtr[channel].fallingEdgeAlarm.alarm));
                writel(regValue, devPtr->base + PVT_HYST_F(channel));
                break;

            default:
                errorId = MCUEXT_E_PARAM_CONFIG;
                break;
            }

            if (E_OK == errorId)
            {
                McuExt_Ip_PvtUpdateAlarmMode(devPtr, channel, alarm, TRUE);
            } /* else not needed */
        }
    } /* else not needed */

    return errorId;
}

/** *****************************************************************************************************
 * \brief This function deinit pvt for disable all alarm in all channel.
 *
 * \verbatim
 * Syntax             : void McuExt_Ip_PvtEnableDisableAlarm(McuExt_PvtChannelIdType channel,
 *                                                          McuExt_PvtAlarmType alarm, boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function deinit pvt for disable all alarm in all channel.
 *                      temperature can get.
 * \endverbatim
 *******************************************************************************************************/
void McuExt_Ip_PvtEnableDisableAlarm(McuExt_PvtChannelIdType channel, McuExt_PvtAlarmType alarm, boolean enable)
{
    McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();

    McuExt_Ip_PvtUpdateAlarmMode(devPtr, channel, alarm, enable);
}

/** *****************************************************************************************************
 * \brief This function deinit pvt for disable all alarm in all channel.
 *
 * \verbatim
 * Syntax             : void McuExt_Ip_PvtDeinit(void)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function deinit pvt for disable all alarm in all channel.
 *                      temperature can get.
 * \endverbatim
 *******************************************************************************************************/
/*PRQA S 1505 1*/
void McuExt_Ip_PvtDeinit(void)
{
    uint32 base;
    uint32 channel;
    McuExt_PvtChannelType *channelPtr;
    McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();

    base = devPtr->base;

    for (channel = (uint32)PVT_CHANNEL0; channel < (uint32)PVT_CHANNEL_NUMBER; channel++)
    {
        /* PRQA S 4342 1*/
        channelPtr = (McuExt_PvtChannelType *)&devPtr->channel[channel];

        /* Disable all interrupts. */
        writel(0U, base + PVT_INT_EN(channel));

#if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON)
        writel(0U, base + PVT_SEM_IRQ_CTRL_OFF);
#endif /** #if (MCUEXT_PVT_SAFETY_INTERRUPT_ENABLE == STD_ON) */

        SchM_Enter_McuExt_MCUEXT_EXCLUSIVE_AREA_00();
        channelPtr->alarmCb = NULL_PTR;
        channelPtr->alarmEnableMask = 0U;
        SchM_Exit_McuExt_MCUEXT_EXCLUSIVE_AREA_00();
    }

}

/** *****************************************************************************************************
 * \brief This function Stop temperature sensor.
 *
 * \verbatim
 * Syntax             : Std_ReturnType McuExt_Ip_PvtStop(void)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function Stop temperature sensor.temperature can not get.
 * \endverbatim
 *******************************************************************************************************/
/* PRQA S 3673 1 */
void McuExt_Ip_PvtStop(void)
{
    const McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();
    uint32 regValue = readl(devPtr->base + PVT_CTRL);

    /* Disable T sensor */
    regValue |= BM_PVT_CTRL_PDTSEN;
    writel(regValue, devPtr->base + PVT_CTRL);

    /* Clear initialize state */
    McuExt_PvtInitializeState = MCUEXT_PVT_UNINIT;
    McuExt_PvtConfigPtr = NULL_PTR;
}

/** *****************************************************************************************************
 * \brief This function get temperature value.
 *
 * \verbatim
 * Syntax             : Std_ReturnType McuExt_Ip_PvtGet(float32 *temperaturePtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *
 * Parameters (inout) : temperaturePtr - pointer to pvt value
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : This function get temperature value.
 *                      Temperature value is not ready until 280ms after McuExt_Ip_PvtStart() is called.
 * \endverbatim
 * Traceability       : SWSR_MCU_051 SW_SM001
 *******************************************************************************************************/
Std_ReturnType McuExt_Ip_PvtGet(float32 *temperaturePtr)
{
    Std_ReturnType errorId = E_OK;
    uint32 dout;
    McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();

    if (FALSE == McuExt_Ip_PvtIsTempSensorRunning(devPtr))
    {
        errorId = MCUEXT_E_PVT_STOP;
    }
    else
    {
        /*
        * Read temperaturePtr data. PVT_DOUT is automatically updated every 280ms
        * after McuExt_Ip_PvtStart() is called.
        */
        dout = (readl(devPtr->base + PVT_DOUT) >> PVT_DOUT_DOUT) &
               PVT_BIT_MASK(PVT_THRESH_BITS);

        /* Convert data to Celsius. */
        *temperaturePtr = McuExt_Ip_PvtDoutToCelsius(dout);
    }

    return errorId;
}

/** *****************************************************************************************************
 * \brief This function clear alarm status according to channel and alarm type for pvt.
 *
 * \verbatim
 * Syntax             : void McuExt_Ip_PvtClearStatus(McuExt_PvtChannelIdType channel,
                                     McuExt_PvtAlarmType alarm)
 *
 * Service ID[hex]    : 0x36
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel id
 *                      alarm - alarm type
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function clear alarm status according to channel and alarm type for pvt.
 * \endverbatim
 *******************************************************************************************************/
/* PRQA S 3673 1 */
void McuExt_Ip_PvtClearStatus(McuExt_PvtChannelIdType channel, McuExt_PvtAlarmType alarm)
{
    const McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();
    uint32 regValue = readl(devPtr->base + PVT_INT_CLR(channel));

    regValue |= (1UL << PVT_ALARM_INT(alarm));
    writel(regValue, devPtr->base + PVT_INT_CLR(channel));

    regValue &= ~(1UL << PVT_ALARM_INT(alarm));
    writel(regValue, devPtr->base + PVT_INT_CLR(channel));
}

/** *****************************************************************************************************
 * \brief This function clear alarm status according to channel and alarm type for pvt.
 *
 * \verbatim
 * Syntax             : boolean McuExt_Ip_PvtGetStatus(McuExt_PvtChannelIdType channel, McuExt_PvtAlarmType alarm)
 *
 * Service ID[hex]    : 0x36
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : devPtr - pointer to pvt device
 *                      channel - channel id
 *                      alarm - alarm type
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *                      E_OK for success and others for failure.
 *
 * Description        : This function clear alarm status according to channel and alarm type for pvt.
 * \endverbatim
 *******************************************************************************************************/
boolean McuExt_Ip_PvtGetStatus(McuExt_PvtChannelIdType channel, McuExt_PvtAlarmType alarm)
{
    const McuExt_PvtType *devPtr = MCUEXT_PVT_GET_DEVICEINFO();
    uint32 regValue = readl(devPtr->base + PVT_INT_STATUS(channel));
    boolean status;

    status = (boolean)((regValue >> (uint32)alarm) & 0x1U);

    return status;
}
/** *****************************************************************************************************
 * \brief This function enable temperature monitor.
 *
 * \verbatim
 * Syntax             : Std_ReturnType McuExt_Ip_PvtInit(const McuExt_PvtAlarmConfigType *configPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : errorId
 *
 * Description        : Set Temperature monitoring of PVT sensor. Configure the temperature alarm type and threshold on EB;
 *  1 Temperature highest thresholds alarm configuration:
 *            - After exceeding highest thresholds trigger a system reset.
 *  2 Temperature high alarm configuration:
 *              - After exceeding thresholds, a warning is triggered,User alarm settings can be made in the function "Mcu_Ip_PvtAlarmCb".
 *  3 Temperature rise alarm configuration:
 *              - After exceeding T1 degrees, the hardware starts the high temperature alarm monitoring,
 *              - After exceeding T2 degrees, a temperature rise warning is triggered,User alarm settings can be made in the function "Mcu_Ip_PvtAlarmCb".
 *  4 Temperature low alarm configuration:
 *              - After below thresholds, a warning is triggered,User alarm settings can be made in the function "Mcu_Ip_PvtAlarmCb".
 *  5 Temperature fall alarm configuration:<p/>
 *              - After below T1 degrees, the hardware starts the low temperature alarm monitoring,
 *              - After below T2 degrees, a temperature fall warning is triggered,User alarm settings can be made in the function "Mcu_Ip_PvtAlarmCb".
 *              Note: Choose one of the four 2)-5)
 *                    Mcu_PvtApDev is disabled by default,Configure the Mcu_PvtApDev enable on EB.
 * \endverbatim
 *******************************************************************************************************/
Std_ReturnType McuExt_Ip_PvtInit(const McuExt_PvtAlarmConfigType *configPtr)
{
    Std_ReturnType errorId = E_OK;
    uint32 index;
    uint32 regValue;
    McuExt_PvtType *pvtDevPtr = MCUEXT_PVT_GET_DEVICEINFO();

    McuExt_Ip_PvtPrepare(pvtDevPtr, configPtr);

    /*use channel0 as reset when temp over highest*/
    if (configPtr[PVT_CHANNEL0].configOption != 0U)
    {
        McuExt_Ip_PvtRegisterAlarmCb(pvtDevPtr, PVT_CHANNEL0,
                                    configPtr[PVT_CHANNEL0].pvtNotification);
    }/* else not needed */

    /*use channel1 as reset when temp over highest*/
    if (configPtr[PVT_CHANNEL1].configOption != 0U)
    {
        McuExt_Ip_PvtRegisterAlarmCb(pvtDevPtr, PVT_CHANNEL1,
                                    configPtr[PVT_CHANNEL1].pvtNotification);
    }/* else not needed */

    McuExt_Ip_PvtStart(pvtDevPtr);

    for (index = (uint32)PVT_CHANNEL0; index < (uint32)PVT_CHANNEL_NUMBER; index++)
    {
        if ((configPtr[index].configOption & PVT_HIGH_LOW_ALARM) != 0U)
        {
            /* PRQA S 4342 2 */
            errorId = McuExt_Ip_PvtEnableAlarm(pvtDevPtr, (McuExt_PvtChannelIdType)index, PVT_HIGH_LEVEL_ALARM);
            errorId |= McuExt_Ip_PvtEnableAlarm(pvtDevPtr, (McuExt_PvtChannelIdType)index, PVT_LOW_LEVEL_ALARM);
        }/* else not needed */

        if ((configPtr[index].configOption & PVT_RISING_ALARM) != 0U)
        {
            /* PRQA S 4342 1 */
            errorId |= McuExt_Ip_PvtEnableAlarm(pvtDevPtr, (McuExt_PvtChannelIdType)index, PVT_RISING_EDGE_ALARM);
        }/* else not needed */

        if ((configPtr[index].configOption & PVT_FALLING_ALARM) != 0U)
        {
            /* PRQA S 4342 1 */
            errorId |= McuExt_Ip_PvtEnableAlarm(pvtDevPtr, (McuExt_PvtChannelIdType)index, PVT_FALLING_EDGE_ALARM);
        }/* else not needed */

        if ((configPtr[index].configOption & PVT_DISABLE_GOLBAL_RESET) != 0U)
        {
            /* Only pvt channel0 need to be enabled, default is disabled and will be reset as over highest temperature threshold. */
            regValue = readl(pvtDevPtr->base + PVT_EXTRA_CFG);
            regValue &= ~(1UL << PVT_EXTRA_CFG_PVT_PMU_INT_0_EN);
            writel(regValue, pvtDevPtr->base + PVT_EXTRA_CFG);
        }/* else not needed */
    }

    return errorId;
}

#define MCUEXT_STOP_SEC_CODE
#include "McuExt_MemMap.h"

#ifdef __cplusplus
}

#endif
/* End of file */
